package com.vinjogames.util;

import com.vinjogames.entities.Player;

public class TechTree {
	private boolean playerTree[][];
	private int techBudget;
	
	public TechTree() {
		this.LoadDefaultTechs();
//		this.techBudget = GameConVars.PLAYER_TECHNOLOGY_BUDGET;
		this.techBudget = 0;
	}
	
	public TechTree(int budget) {
		this.LoadDefaultTechs();
		techBudget = budget;
	}
	
	private void LoadDefaultTechs() {
		playerTree = new boolean[GameConVars.TECH_TREES][GameConVars.TECH_TREE_TOTALS];
		for(int i = 0; i < GameConVars.TECH_TREES; ++i)
			for(int j = 0; j < GameConVars.TECH_TREE_TOTALS; ++j)
				playerTree[i][j] = false;
	}
	
	private boolean activateTech(int treeNum, int techNum) {
		if(checkTechReqIsMet(treeNum, techNum)) {
			return (playerTree[treeNum][techNum] = true);
		}
		return false;
	}
		
	public int desiredTechDepth(int techNum) {
		int i;
		for(i = 1; i <= GameConVars.TECH_DEPTH; ++i) {
			if(techNum < GameConVars.TECH_LEVELS[i])
					return i - 1;
		}
		return i - 1;
	}
	
	/**
	 * 
	 * Checks if the player meets the requirements to research the specified technology.
	 * 
	 * @param treeNum The tree in which to research.
	 * @param techNum The technology to research.
	 * @return true if requirements are met.
	 */
	public boolean checkTechReqIsMet(int treeNum, int techNum) {
		if(techBudget >= GameConVars.PLAYER_TECHNOLOGY_BUDGET ||
		   techNum > GameConVars.TECH_TREE_TOTALS ||
		   treeNum > GameConVars.TECH_TREES ||
		   playerTree[treeNum][techNum])
			return false;
		
		int desiredLevel = desiredTechDepth(techNum);
		if(checkLevelIsMet(treeNum, desiredLevel)) return true;
		return false;
	}
	
	private boolean checkLevelIsMet(int treeNum, int levelNum) {
		if(levelNum < 1) return true;
		for(int i = GameConVars.TECH_LEVELS[levelNum - 1]; i < GameConVars.TECH_LEVELS[levelNum]; ++i)
			if(playerTree[treeNum][i]) return true;
		return false;
	}
	
	public boolean playerResearchTechnology(Player p, int treeNum, int techNum) {
		if(activateTech(treeNum, techNum)) {
			switch(treeNum) {
			case GameConVars.ECONOMIC_TREE:
				switch(techNum) {
				case GameConVars.HighYieldMining://Increases AP per turn provided by base.
					p.increaseResourcesPerTurn(GameConVars.BonusAP);
					break;
				case GameConVars.ForwardSupplyPosts://Units heal 10% HP per turn (@ turn start).
					p.setUnitHealPerTurn(p.getUnitHealPerTurn() + GameConVars.BonusHeal);
					break;
				case GameConVars.Sabotage://Unlocks unit: Saboteurge-X3.
					p.setSabotageUnlocked(true);
					break;
				case GameConVars.CombatEngineering://Units contribute double towards capturing resources.
					p.setUnitResourceCapContribution(p.getUnitResourceCapContribution() * 2);
					break;
				case GameConVars.AssemblyLineManufacturing://% chance per turn to receive a basic tank for free.
					p.setChanceAtFreeUnit(p.getChanceAtFreeUnit() + GameConVars.LotteryTank);
					break;
				case GameConVars.CostEfficiency://Unlocks unit: Mark-ET Siege Tank.
					p.setMarketTankUnlocked(true);
					break;
				}
				break;
			case GameConVars.DESTRUCTIVE_TREE:
				switch(techNum) {
				case GameConVars.AdvancedShellCasings: //Increases damage of attacks.
					p.setDamageMultiplier(GameConVars.ShellCasingDamageBonus + p.getDamageMultiplier());
					break;
				case GameConVars.CollateralDamage: //Increases radius of attack explosions.
					p.setDamageRadiusMultiplier(GameConVars.CollateralAreaBonus + p.getDamageRadiusMultiplier());
					break;
				case GameConVars.Bombardment: //Unlocks unit: Artillary tank.
					p.setArtillaryUnlocked(true);
					break;
				case GameConVars.FrontlineReinforcement: //Sacrifice movement radius of all units for a decrease in damage taken.
					p.setMovementMultiplier(GameConVars.FrontLineMovementPenalty + p.getMovementMultiplier());
					p.setDamageTakenMultiplier(GameConVars.FrontLineDefenseBonus + p.getDamageTakenMultiplier());
					break;
				case GameConVars.UltraCompactShelling: //Sacrifice attack range of all units for an increase in damage dealt.
					p.setRangeMultiplier(GameConVars.CompactShellingRangePenalty + p.getRangeMultiplier());
					p.setDamageMultiplier(GameConVars.CompactShellingDamageBonus + p.getDamageMultiplier());
					break;
				case GameConVars.BattlefieldControl: //Unlocks unit: Behemoth-BFG88 Tank.
					p.setMegaTankUnlocked(true);
					break;
				}
				break;
			case GameConVars.TACTICAL_TREE:
				switch(techNum) {
				case GameConVars.TitaniumTreads: //Increase distance units can move per AP by 10%.
					p.setMovementMultiplier(GameConVars.TreadMovement + p.getMovementMultiplier());
					break;
				case GameConVars.LaserTargeting: //Decrease random accuracy factor of attacks by 20%.
					p.setAccuracyMultiplier(GameConVars.LaserTargetingBonus + p.getAccuracyMultiplier());
					break;
				case GameConVars.Reconaissance: //Unlocks unit: Scout Tank.
					p.setReconTankUnlocked(true);
					break;
				case GameConVars.AdvancedTactics: //Units can move after firing.
					p.setMoveAfterFire(true);
					break;
				case GameConVars.AirborneInvasion: //Spend AP to air-drop the next created unit up to X distance from base.
					p.setAirDropEnabled(true);
					break;
				case GameConVars.TacticalStrikes: //Unlocks unit: Falcon-T6 Assault Chopper.
					p.setHelicopterUnlocked(true);
					break;
				}
				break;
			}
			++techBudget;
			return true;
		}
		return false;
	}
	
	/**
	 * 
	 * Checks to see if a player has researched a technology.
	 * 
	 * @param techTree The technology tree to check.
	 * @param tech The technology in question.
	 * @return True if the player has researched the tech, false if not.
	 */
	public boolean doesPlayerOwnTech(int techTree, int tech) {
		return playerTree[techTree][tech];
	}
	
	//Getters and setters
	//public boolean[][] getPlayerTree() { return playerTree.clone(); }
	public int getTechBudget() { return techBudget; }	
}
